package cn.nangzi.study.oauth.conf;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.web.header.HeaderWriter;

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
	
	@Autowired
	private DataSource dataSource;
	
	@Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        TokenStore tokenStore = new JdbcTokenStore(dataSource);
        resources.resourceId("user-services")
                .tokenStore(tokenStore).stateless(false);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
	        .sessionManagement()
	        .sessionCreationPolicy(SessionCreationPolicy.NEVER)
	    .and()
	        .requestMatchers().antMatchers("/user/**")
	    .and()
            // For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security
            // will respond with an HTTP 401 nonetheless.
            // So we just put all other requests types under OAuth control and exclude OPTIONS.
            .authorizeRequests()
                .antMatchers(HttpMethod.GET, "/user/**").access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.POST, "/user/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PATCH, "/user/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, "/user/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, "/user/**").access("#oauth2.hasScope('write')")
        .and()
            // Add headers required for CORS requests.
            .headers().addHeaderWriter(new HeaderWriter() {
				@Override
				public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
					response.addHeader("Access-Control-Allow-Origin", "*");
	                if (request.getMethod().equals("OPTIONS")) {
	                    response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
	                    response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
	                }
				}
			});
    }

}